package com.alone.wchat.common.net;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.velocity.VelocityEngineFactoryBean;
import org.springframework.ui.velocity.VelocityEngineUtils;

import javax.mail.internet.MimeMessage;
import java.io.*;
import java.util.Map;
import java.util.Properties;

/**
 * 
 * email工具类，提供基本的邮件发送功能
 * 
 * @author weirdor
 *
 */
public class EmailUtils {
	private static Logger logger = LoggerFactory.getLogger(EmailUtils.class);

	// 默认邮件配置
	private static final Properties DEFAULT_MAIL_CONFIG = new Properties();
	static {
		InputStream inStream = EmailUtils.class.getClassLoader().getResourceAsStream("default_mail_config.properties");
		logger.info("邮件工具类初始化，读取默认邮件配置 classpath:default_mail_config.properties");
		try {
			DEFAULT_MAIL_CONFIG.load(inStream);
		} catch (IOException e) {
			e.printStackTrace();
			logger.info("读取默认邮件配置 classpath:default_mail_config.properties 出错：" + e);
		}
	}

	/**
	 * 发送普通的文本邮件
	 * 
	 * @param receivers
	 *            接收者
	 * @param ccs
	 *            抄送
	 * @param subject
	 *            主题
	 * @param text
	 *            文本内容
	 */
	public static void sendTextMail(Properties sendConfig, String[] receivers, String[] ccs, String subject,
			String text) {
		if (sendConfig == null || sendConfig.size() == 0) {
			sendConfig = DEFAULT_MAIL_CONFIG;
		} else {
			checkConfig(sendConfig);
		}

		SimpleMailMessage simpleMailMessage = new SimpleMailMessage();

		simpleMailMessage.setTo(receivers);
		simpleMailMessage.setCc(ccs);

		try {
			String nick = javax.mail.internet.MimeUtility.encodeText(sendConfig.getProperty("senderNickname", ""));
			simpleMailMessage.setFrom(nick + " <" + sendConfig.getProperty("username") + ">");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			simpleMailMessage.setFrom(sendConfig.getProperty("username"));
		}

		simpleMailMessage.setSubject(subject);
		simpleMailMessage.setText(text);

		getMailSender(sendConfig).send(simpleMailMessage);
	}

	/**
	 * 发送带附件的邮件
	 * 
	 * @param receivers
	 *            接收者
	 * @param subject
	 *            主题
	 * @param text
	 *            文本内容
	 * @param htmlFlag
	 *            HTML标记
	 * @param filePath
	 *            附件路径
	 */
	public static void sendWithAttachment(Properties sendConfig, String[] receivers, String[] ccs, String subject,
			String text, boolean htmlFlag, String filePath) {

		if (sendConfig == null || sendConfig.size() == 0) {
			logger.info("发送时未指定邮件配置，将启用默认配置");
			sendConfig = DEFAULT_MAIL_CONFIG;
		} else {
			logger.info("发送时已指定邮件配置，默认配置将被忽略");
			checkConfig(sendConfig);
		}

		JavaMailSender mailSender = getMailSender(sendConfig);

		MimeMessage mimeMessage = mailSender.createMimeMessage();
		try {
			MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
			messageHelper.setTo(receivers);
			messageHelper.setCc(ccs);
			
			try {
				String nick = javax.mail.internet.MimeUtility.encodeText(sendConfig.getProperty("senderNickname", ""));
				messageHelper.setFrom(nick + " <" + sendConfig.getProperty("username") + ">");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				messageHelper.setFrom(sendConfig.getProperty("username"));
			}

			messageHelper.setSubject(subject);
			messageHelper.setText(text, htmlFlag);

			if (filePath != null && new File(filePath).exists()) {
				FileSystemResource file = new FileSystemResource(new File(filePath));
				messageHelper.addAttachment(file.getFilename(), file);
			}
			mailSender.send(mimeMessage);

			logger.info("已发送邮件 [{}] 至 {}，抄送{}", subject, receivers, ccs);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("发送邮件 [{}] 失败,错误信息:{}", subject, e.toString());
		}
	}

	/**
	 * 发送基于VelocityTemplate模板的邮件 <div> commons包在<b>classpath</b>下的
	 * <b>emailTemplate</b> 目录中提供了一些模板，可直接指定，具体如下：
	 * <ol>
	 * <li>50x.html，服务端错误统一模板</li>
	 * <li>getHuanxinTokenFailed.html，获取环信token错误模板</li>
	 * <li>registHuanxinFailed.html，注册环信用户错误模板</li>
	 * <li>payErrorNotify.html，支付错误模板</li>
	 * </ol>
	 * 模板所需的数据要根据模板而定 </div>
	 * 
	 * @param sendConfig
	 *            邮件配置
	 * @param receivers
	 *            收件人
	 * @param ccs
	 *            抄送人
	 * @param subject
	 *            主题
	 * @param model
	 *            模板数据
	 * @param templatePath
	 *            模板所在的路径，<b>需在classpath下</b>，如 "emailTemplate/demo.html"
	 *            表示classpath下的emailTemplate目录下的demo.html模板
	 * @param templateName
	 *            模板名称
	 */
	public static void sendWithVelocityTemplate(Properties sendConfig, String[] receivers, String[] ccs, String subject,
			Map<String, Object> model, String templatePath) {
		String result = null;
		try {
			ClassPathResource resource = new ClassPathResource(templatePath);
			if (!resource.exists()) {
				throw new FileNotFoundException("指定资源" + templatePath + "不存在");
			}
			String urlStr = resource.getURL().toString();

			int splitIndex = urlStr.lastIndexOf("/");
			String resourceLoaderPath = urlStr.substring(0, splitIndex);
			String resourceName = urlStr.substring(splitIndex + 1);

			VelocityEngineFactoryBean vef = new VelocityEngineFactoryBean();
			vef.setResourceLoaderPath(resourceLoaderPath);

			result = VelocityEngineUtils.mergeTemplateIntoString(vef.createVelocityEngine(), resourceName, "UTF-8",
					model);
			sendWithAttachment(sendConfig, receivers, ccs, subject, result, true, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void checkConfig(Properties sendConfig) {

	}

	private static JavaMailSender getMailSender(Properties sendConfig) {
		JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
		logger.info("使用邮件配置 {}", sendConfig);
		mailSender.setHost(sendConfig.getProperty("host"));
		mailSender.setUsername(sendConfig.getProperty("username"));
		mailSender.setPassword(sendConfig.getProperty("password"));
		mailSender.setPort(Integer.valueOf(sendConfig.getProperty("port")));

		String defaultEncoding = sendConfig.getProperty("defaultEncoding", "UTF-8");

		mailSender.setDefaultEncoding(defaultEncoding);

		Properties javaMailProperties = new Properties();

		String sslEncryption = sendConfig.getProperty("TLS_SSL_Encryption");
		if (sslEncryption != null && sslEncryption.toLowerCase().equals("true")) {
			javaMailProperties.put("mail.smtp.starttls.enable", "true");
		}

		mailSender.setJavaMailProperties(javaMailProperties);

		return mailSender;
	}

	/**
	 * 验证email是否有效
	 * 
	 * @param email
	 * @return 有效true，无效false
	 */
	public static boolean validateEmail(String email) {
		return email != null
				&& email.matches("^[a-zA-Z0-9_-]((\\.)*[a-zA-Z0-9_-])+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$");
	}
}
